package com.zhuanzhuan.hero.user.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.entity.HeroUserInfo;
import com.zhuanzhuan.hero.user.entity.HeroUserVisitRecord;
import com.zhuanzhuan.hero.user.enums.ExceptionMsgEnum;
import com.zhuanzhuan.hero.user.enums.StateEnum;
import com.zhuanzhuan.hero.user.mapper.HeroUserVisitRecordMapper;
import com.zhuanzhuan.hero.user.service.HeroUserInfoService;
import com.zhuanzhuan.hero.user.service.HeroUserVisitRecordService;
import com.zhuanzhuan.hero.user.service.IBuryingPointService;
import com.zhuanzhuan.hero.user.service.IUserService;
import com.zhuanzhuan.hero.user.util.Assert;
import com.zhuanzhuan.hero.user.vo.UserItemBriefVO;
import com.zhuanzhuan.hero.user.vo.UserListItemVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * dal Interface:HeroUserVisitRecord
 * @author hanjunjun
 * @date 2024-7-2
 */
@Service
@Slf4j
public class HeroUserVisitRecordServiceImpl extends ServiceImpl<HeroUserVisitRecordMapper, HeroUserVisitRecord>
    implements HeroUserVisitRecordService {

    @Resource
    private HeroUserInfoService userInfoService;

    @Resource
    private IUserService userService;

    @Resource
    private IBuryingPointService buryingPointService;

    @Override
    public void clearVisitRecord(Long uid) {
        log.info("clearVisitRecord uid={}", uid);
        Assert.notNull(uid, ExceptionMsgEnum.PARAM_ERROR);
        LambdaUpdateWrapper<HeroUserVisitRecord> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserVisitRecord::getState, StateEnum.IS_DELETED.getCode())
            .eq(HeroUserVisitRecord::getToUid, uid)
            .eq(HeroUserVisitRecord::getState, StateEnum.EFFECTIVE.getCode());
        this.update(updateWrapper);
    }

    @Override
    public void saveVisitRecord(Long fromUid, Long toUid) {
        log.info("saveVisitRecord fromUid={}, toUid={}", fromUid, toUid);
        if (fromUid.equals(toUid)) {
            log.info("不记录自己访问自己");
            return;
        }

        //埋点
        buryingPointService.visitRecord(fromUid, toUid);

        //如果formUid关闭【展示访客记录】开关，则不记录
        HeroUserInfo heroUserInfo = userInfoService.getUserByUid(fromUid);
        Assert.notNull(heroUserInfo, ExceptionMsgEnum.BUSINESS_ERROR);

        Integer isShowVisitor = heroUserInfo.getIsShowVisitor();
        if (!NumConsts.ONE.equals(isShowVisitor)) {
            log.info("{}关闭展示访客记录，不记录", fromUid);
            return;
        }

        this.save(this.buildEntity(fromUid, toUid));
    }

    @Override
    public List<UserListItemVO> queryVisitRecordList(Long selfUid, Long homemakerUid) {
        //查询访客记录
        //被访问者uid   如果homemakerUid不为空说明是客态查看访客记录，被访问者就是homemakerUid  否则是主态查看自己的访客记录，即selfUid
        Long intervieweeUid = Objects.isNull(homemakerUid) || homemakerUid.equals(selfUid) ? selfUid : homemakerUid;
        List<HeroUserVisitRecord> visitRecords = this.queryDistinctRecord(intervieweeUid, NumConsts.THIRTY, NumConsts.HUNDRED);
        if (CollectionUtils.isEmpty(visitRecords)) {
            log.info("访客记录为空");
            return new ArrayList<>();
        }

        //访问者uid
        List<Long> visitorUids =
            visitRecords.stream().map(HeroUserVisitRecord::getFromUid)
                .distinct().collect(Collectors.toList());

        List<UserItemBriefVO> userItems = userService.buildUserItem(selfUid, visitorUids, true, true);
        Map<Long, UserItemBriefVO> uidUserMap =
            userItems.stream().collect(Collectors.toMap(UserItemBriefVO::getUid, Function.identity()));

        return visitRecords.stream()
            .map(visitRecord -> this.convertUserListItemVO(visitRecord, uidUserMap))
            .collect(Collectors.toList());
    }

    @Override
    public List<HeroUserVisitRecord> listByToUid(Long toUid) {
        Assert.notNull(toUid, ExceptionMsgEnum.PARAM_ERROR);
        HeroUserVisitRecord query = new HeroUserVisitRecord();
        query.setToUid(toUid);
        query.setState(StateEnum.EFFECTIVE.getCode());
        return getBaseMapper().select(query);
    }

    /**
     * 访客记录仅展示统一用户最新一条，按照访问时间倒序排列
     *  
     * @param toUid
     * @param days 查最近几天的  正数
     * @param limit
     * @return java.util.List<com.zhuanzhuan.hero.user.entity.HeroUserVisitRecord>
     * @author  hanjunjun  
     * @date 2024/7/2       
     **/
    private List<HeroUserVisitRecord> queryDistinctRecord(Long toUid, int days, int limit) {
        DateTime beginOfDay = DateUtil.beginOfDay(new Date());
        DateTime visitTimeStart = DateUtil.offsetDay(beginOfDay, -days);
        return getBaseMapper().queryDistinctRecord(toUid, StateEnum.EFFECTIVE.getCode(), visitTimeStart, limit);
    }

    public static void main(String []args){
        DateTime beginOfDay = DateUtil.beginOfDay(new Date());
        System.out.println(beginOfDay);
        DateTime dateTime = DateUtil.offsetDay(beginOfDay, -30);
        System.out.println(dateTime);

    }

    private HeroUserVisitRecord buildEntity(Long fromUid, Long toUid) {
        HeroUserVisitRecord record = new HeroUserVisitRecord();
        record.setFromUid(fromUid);
        record.setToUid(toUid);
        record.setState(StateEnum.EFFECTIVE.getCode());
        record.setCreateBy(NumConsts.SYSTEM_CODE);
        record.setUpdateBy(NumConsts.SYSTEM_CODE);
        return record;
    }

    private UserListItemVO convertUserListItemVO(HeroUserVisitRecord visitRecord, Map<Long, UserItemBriefVO> uidUserMap) {
        UserListItemVO vo = new UserListItemVO();
        vo.setId(visitRecord.getId()).setCreateTime(visitRecord.getCreateTime());
        vo.setUserInfo(uidUserMap.get(visitRecord.getFromUid()));

        return vo;
    }

}